/*****************************************************************************
 *   Copyright 2005 Tim A Wang
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 ****************************************************************************/
package com.jb.web.bean.inspector;

import com.jb.framework.Registry;
import com.jb.web.bean.FormField;
import com.jb.web.bean.HtmlItem;
import com.jb.web.context.WebContext;

import java.beans.PropertyEditor;
import java.beans.PropertyEditorSupport;

import java.util.HashMap;

import com.jb.faces.component.UIComponent;


/**
 * PropertyEditor allows
 */
public class DefaultPropertyEditor extends PropertyEditorSupport {
    private static HashMap pes = new HashMap();
    private static HashMap categories = new HashMap();
    private static Registry propertyRegistiry = new Registry() {
            public boolean testRegistration(Object pRegistered, Object pTestObj) {
                if (!(pRegistered instanceof Class)) {
                    return false;
                }

                Class clazz = (Class) pRegistered;

                return clazz.isInstance(pTestObj);
            }
        };

    String mWindowURL = "pe.jsp";
    String strValue;
    WebContext ctx;
    int mHeight = 200;
    int mWidth = 320;
    /**
     * Default constructor
     */
    public DefaultPropertyEditor() {
    }
    /**
     * Constructor
     * @param url 
     * @param pageName
     */
    public DefaultPropertyEditor(String url, String pageName) {
        mWindowURL = url;
    }
    
    public static String getPropertyCategory(Object component, String propertyName) {
        if(component==null)
            return "undefined";
       
        return (String) categories.get(propertyName);
    }
    /**
     * Returns a property editor for a given property field item based on 
     * the model bean the property is to edit.
     *
     * @param item the PropertyField requires property editor.
     *
     * @return A property editor.
     */
    public static PropertyEditor getEditor(PropertyField item) {
        PropertyEditor pe = getEditor(item.getModelBean(), item.getClientId());

        if (pe != null) {
            return pe;
        }

        pe = (PropertyEditor) pes.get(item.getClientId());

        if (pe == null) {
            return new DefaultPropertyEditor();
        } else {
            return pe;
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param object DOCUMENT ME!
     * @param propertyName DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public static PropertyEditor getEditor(Object object, String propertyName) {
        if (object == null) {
            return null;
        }

        PropertyEditor pe = getEditor(object.getClass(), propertyName);

        return pe;
    }

    /**
     * DOCUMENT ME!
     *
     * @param propertyClass DOCUMENT ME!
     * @param propertyName DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public static PropertyEditor getEditor(Class propertyClass, String propertyName) {
        if (propertyClass == null) {
            return null;
        }

        PropertyEditor pe = (PropertyEditor) pes.get(propertyClass.getName() + "." + propertyName);

        if ((pe == null) && (propertyClass.getSuperclass() != null) && (propertyClass.getSuperclass() != Object.class)) {
            pe = getEditor(propertyClass.getSuperclass(), propertyName);
        }

        return pe;
    }

    /**
     * DOCUMENT ME!
     *
     * @param value DOCUMENT ME!
     */
    public void setAsText(String value) {
        strValue = value;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getAsText() {
        return strValue;
    }

    /**
     * DOCUMENT ME!
     *
     * @param height DOCUMENT ME!
     */
    public void setHeight(int height) {
        this.mHeight = height;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public int getHeight() {
        return mHeight;
    }

    /**
     * DOCUMENT ME!
     *
     * @param pPropertyName DOCUMENT ME!
     * @param host DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public static boolean isPublished(String pPropertyName, Object host) {
        return propertyRegistiry.isRegistered(pPropertyName.toUpperCase(), host);
    }

    /**
     * DOCUMENT ME!
     *
     * @param pItem DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getURL(HtmlItem pItem) {
        return getWindowURL() + "?pageMode=dialog&id=" + pItem.getId();
    }

    /**
     * DOCUMENT ME!
     *
     * @param propertyClass DOCUMENT ME!
     * @param propertyName DOCUMENT ME!
     * @param pe DOCUMENT ME!
     */
    public static void addPropertyEditor(Class propertyClass, String propertyName, PropertyEditor pe) {
        pes.put(propertyClass.getName() + "." + propertyName, pe);
    }

    /**
     * DOCUMENT ME!
     *
     * @param propertyName DOCUMENT ME!
     * @param pe DOCUMENT ME!
     */
    public static void addPropertyEditor(String propertyName, PropertyEditor pe) {
        pes.put(propertyName, pe);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public Object getValue() {
        return strValue;
    }

    /**
     * Sets width of the editor window in pixels
     *
     * @param width new width.
     */
    public void setWidth(int width) {
        this.mWidth = width;
    }

    /**
     * Returns width of the editor window in pixels.
     *
     * @return DOCUMENT ME!
     */
    public int getWidth() {
        return mWidth;
    }

    /**
     * Sets editor window URL.
     *
     * @param windowURL new URL.
     */
    public void setWindowURL(String windowURL) {
        this.mWindowURL = windowURL;
    }

    /**
     * Returns URL for editor window.
     *
     * @return URL.
     */
    public String getWindowURL() {
        return this.mWindowURL;
    }

    /**
     * Registers a property for property editor
     *
     * @param pClass Class of the property
     * @param pType Category of the property
     * @param pPropertyName Name of the property
     */
    public static void publish(Class pClass, String pType, String pPropertyName) {
        categories.put(pPropertyName, pType);
        propertyRegistiry.register(pPropertyName.toUpperCase(), pClass);
    }

    /**
     * Publishes a property to inspector with an editor
     *
     * @param pClass class for the property 
     * @param pType category of the property
     * @param pPropertyName name of the property
     * @param pe property editor for the property
     */
    public static void publish(Class pClass, String pType, String pPropertyName, PropertyEditor pe) {
        categories.put(pPropertyName, pType);
        propertyRegistiry.register(pPropertyName.toUpperCase(), pClass);
        addPropertyEditor(pClass, pPropertyName, pe);
    }

    public void setContext(WebContext ctx) {
        this.ctx = ctx;
    }

    public WebContext getContext() {
        return ctx;
    }

    /**
     * Renders the item to an input field.
     *
     * @param ctx Runtime context.
     * @param itemToRender field to be rendered.
     *
     * @return String representation of the field(in html snippets.
     */
    public StringBuffer render(WebContext ctx, UIComponent itemToRender) {
        FormField pItem = (FormField) itemToRender;
        String objValue = pItem.getValue();
        StringBuffer html = new StringBuffer().append("<INPUT ")
                                              .append(com.jb.web.renderer.RendererImpl.addTagProperty("name",
                    pItem.getClientId(), null))
                                              .append(com.jb.web.renderer.RendererImpl.addTagProperty("id",
                    pItem.getClientId(), null))
                                              .append(com.jb.web.renderer.RendererImpl.addTagProperty("class",
                    "propertyField", null))
                                              .append(com.jb.web.renderer.RendererImpl.addTagProperty("disabled",
                    pItem.isEnabled() ? "" : "disabled", null))
                                              .append(com.jb.web.renderer.RendererImpl.addTagProperty("value",
                    objValue, null)).append(com.jb.web.renderer.RendererImpl.addTagProperty("type", "text", "text"))
                                              .append(">");

        return html;
    }
}
